/*
 * @Author: 糊涂的老知青
 * @Date: 2022-08-13
 * @Version: 1.0.0
 * @Description:
 */
package rabbitmq

import (
	"log"
	"lzq-admin/pkg/snowflake"
	"time"

	"github.com/streadway/amqp"
)

type rabbitMQWork struct {
	LzqRabbitMQ
}

var RabbitMQWorks map[string]*rabbitMQWork

// 初始化Work模式
func NewRabbitMQWork(mqurl string, queueNames []string) {
	for _, v := range queueNames {
		lzqRabbitMQ := NewRabbitMQ(mqurl, v, "", "")
		var err error
		//获取connection
		lzqRabbitMQ.conn, err = amqp.Dial(mqurl)

		lzqRabbitMQ.failOnErr(err, "failed to connect rabbitmq!")
		//获取channel
		lzqRabbitMQ.channel, err = lzqRabbitMQ.conn.Channel()
		lzqRabbitMQ.failOnErr(err, "failed to open a channel")
		RabbitMQWorks[v] = &rabbitMQWork{LzqRabbitMQ: *lzqRabbitMQ}
	}

}

//直接模式下生产者
func (p rabbitMQWork) PublishWork(exchangeName, message, callbackName string) {
	//1.申请队列，如果队列不存在会自动创建，存在则跳过创建
	if _, err := p.channel.QueueDeclare(
		p.QueueName,
		//是否持久化
		false,
		//是否自动删除
		false,
		//是否具有排他性
		false,
		//是否阻塞处理
		false,
		//额外的属性
		nil,
	); err != nil {
		panic(err)
	}

	headers := amqp.Table{
		"msg-id":            snowflake.CreateSnowflakeId(),
		"msg-callback-name": callbackName,
		"msg-name":          exchangeName,
		"msg-senttime":      time.Now(),
	}

	//调用channel 发送消息到队列中
	if err := p.channel.Publish(
		"",
		p.QueueName,
		//如果为true，根据自身exchange类型和routekey规则无法找到符合条件的队列会把消息返还给发送者
		false,
		//如果为true，当exchange发送消息到队列后发现队列上没有消费者，则会把消息返还给发送者
		false,
		amqp.Publishing{
			ContentType: "json/application",
			Body:        []byte(message),
			Headers:     headers,
		}); err != nil {
		panic(err)
	}
}

//直接模式下消费者
func (r rabbitMQWork) ConsumeWork() (delivery <-chan amqp.Delivery, err error) {
	//1.申请队列，如果队列不存在会自动创建，存在则跳过创建
	var q amqp.Queue
	q, err = r.channel.QueueDeclare(
		r.QueueName,
		//是否持久化
		false,
		//是否自动删除
		false,
		//是否具有排他性
		false,
		//是否阻塞处理
		false,
		//额外的属性
		nil,
	)
	if err != nil {
		log.Fatal("Queue Consume: ", err.Error())
		return nil, err
	}

	//接收消息
	delivery, err = r.channel.Consume(
		q.Name, // queue
		//用来区分多个消费者
		"consumer1", // consumer
		//是否自动应答
		false, // auto-ack
		//是否独有
		false, // exclusive
		//设置为true，表示 不能将同一个Conenction中生产者发送的消息传递给这个Connection中 的消费者
		false, // no-local
		//列是否阻塞
		false, // no-wait
		nil,   // args
	)
	if err != nil {
		log.Fatal("Queue Consume: ", err.Error())
		return nil, err
	}

	return delivery, nil
}
